#include "test_math.h"
#include "variable.h"

Q_DECLARE_METATYPE(variable*)

void test_math::ddtest_math_data() {
	QTest::addColumn<QString>("func");
	QTest::addColumn<variable*>("oper1");
	QTest::addColumn<variable*>("result");
	QTest::addColumn<variable*>("resoper1");
	QTest::addColumn<variable*>("resresult");
	variable *oper1,*result,*resoper1,*resresult;
	c_type* value1,*resvalue;
	QString func;
	//ln tests
	func=QString("ln");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=1;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=1;
	resoper1->set_value(value1);
	resvalue->f=1;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=0;
	resresult->set_value(resvalue);
	QTest::newRow("ln(1)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("ln");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=2;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=2;
	resoper1->set_value(value1);
	resvalue->f=1;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=0.693;
	resresult->set_value(resvalue);
	QTest::newRow("ln(2)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("ln");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=3;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=3;
	resoper1->set_value(value1);
	resvalue->f=1;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=1.098;
	resresult->set_value(resvalue);
	QTest::newRow("ln(3)")<<func<<oper1<<result<<resoper1<<resresult;
	//log tests
	func=QString("log");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=1;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=1;
	resoper1->set_value(value1);
	resvalue->f=1;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=0;
	resresult->set_value(resvalue);
	QTest::newRow("log(1)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("log");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=10;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=10;
	resoper1->set_value(value1);
	resvalue->f=0;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=1;
	resresult->set_value(resvalue);
	QTest::newRow("log(10)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("log");
	oper1 = new variable;
	resoper1 = new variable;
	value1 = new c_type;
	resvalue = new c_type;
	resresult = new variable;
	result = new variable;
	value1->f=100;
	oper1->set_value(value1);
	value1 = new c_type;
	value1->f=100;
	resoper1->set_value(value1);
	resvalue->f=1;
	result->set_value(resvalue);
	resvalue = new c_type;
	resvalue->f=2;
	resresult->set_value(resvalue);
	QTest::newRow("log(100)")<<func<<oper1<<result<<resoper1<<resresult;
	//abs tests
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0"));
	resoper1->determine_value(QString("0"));
	result->determine_value(QString("1"));
	resresult->determine_value(QString("0"));
	QTest::newRow("abs(0)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1"));
	resoper1->determine_value(QString("1"));
	result->determine_value(QString("2"));
	resresult->determine_value(QString("1"));
	QTest::newRow("abs(1)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1"));
	resoper1->determine_value(QString("-1"));
	result->determine_value(QString("2"));
	resresult->determine_value(QString("1"));
	QTest::newRow("abs(-1)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.0"));
	resoper1->determine_value(QString("0.0"));
	result->determine_value(QString("1.0"));
	resresult->determine_value(QString("0.0"));
	QTest::newRow("abs(0.0)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.0"));
	resoper1->determine_value(QString("1.0"));
	result->determine_value(QString("2.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("abs(1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("abs");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.0"));
	resoper1->determine_value(QString("-1.0"));
	result->determine_value(QString("2.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("abs(-1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	//exp tests
	func=QString("exp");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.0"));
	resoper1->determine_value(QString("0.0"));
	result->determine_value(QString("2.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("exp(0.0)")<<func<<oper1<<result<<resoper1<<resresult;
	func=QString("exp");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("2.0"));
	resoper1->determine_value(QString("2.0"));
	result->determine_value(QString("2.0"));
	resresult->determine_value(QString("7.390"));
	QTest::newRow("exp(2.0)")<<func<<oper1<<result<<resoper1<<resresult;
	//sin test
	func=QString("sin");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.0"));
	resoper1->determine_value(QString("0.0"));
	result->determine_value(QString("1.0"));
	resresult->determine_value(QString("0.0"));
	QTest::newRow("sin(0.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("3.14"));
	resoper1->determine_value(QString("3.14"));
	result->determine_value(QString("1.0"));
	resresult->determine_value(QString("0.0"));
	QTest::newRow("sin(3.14)")<<func<<oper1<<result<<resoper1<<resresult;
	//cos tests
	func=QString("cos");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.0"));
	resoper1->determine_value(QString("0.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("cos(0.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("3.14"));
	resoper1->determine_value(QString("3.14"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("cos(3.14)")<<func<<oper1<<result<<resoper1<<resresult;
	//tan tests
	func=QString("tan");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.78539"));
	resoper1->determine_value(QString("0.78539"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("tan(0.78539)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("3.14"));
	resoper1->determine_value(QString("3.14"));
	result->determine_value(QString("1.0"));
	resresult->determine_value(QString("0.0"));
	QTest::newRow("tan(3.14)")<<func<<oper1<<result<<resoper1<<resresult;
	//arctan tests
	func=QString("arctan");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.0"));
	resoper1->determine_value(QString("1.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("0.78539"));
	QTest::newRow("arctan(1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("0.0"));
	resoper1->determine_value(QString("0.0"));
	result->determine_value(QString("1.0"));
	resresult->determine_value(QString("0.0"));
	QTest::newRow("arctan(0.0)")<<func<<oper1<<result<<resoper1<<resresult;
	//trunc tests
	func=QString("trunc");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.0"));
	resoper1->determine_value(QString("1.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("trunc(1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.1"));
	resoper1->determine_value(QString("1.1"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("trunc(1.1)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.0"));
	resoper1->determine_value(QString("-1.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("trunc(-1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.1"));
	resoper1->determine_value(QString("-1.1"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("trunc(-1.1)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.6"));
	resoper1->determine_value(QString("1.6"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("trunc(1.6)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.6"));
	resoper1->determine_value(QString("-1.6"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("trunc(-1.6)")<<func<<oper1<<result<<resoper1<<resresult;
	//round tests
	func=QString("round");
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.0"));
	resoper1->determine_value(QString("1.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("round(1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.1"));
	resoper1->determine_value(QString("1.1"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("1.0"));
	QTest::newRow("round(1.1)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.0"));
	resoper1->determine_value(QString("-1.0"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("round(-1.0)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.1"));
	resoper1->determine_value(QString("-1.1"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-1.0"));
	QTest::newRow("round(-1.1)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("1.6"));
	resoper1->determine_value(QString("1.6"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("2.0"));
	QTest::newRow("round(1.6)")<<func<<oper1<<result<<resoper1<<resresult;
	oper1 = new variable;
	resoper1 = new variable;
	resresult = new variable;
	result = new variable;
	oper1->determine_value(QString("-1.6"));
	resoper1->determine_value(QString("-1.6"));
	result->determine_value(QString("0.0"));
	resresult->determine_value(QString("-2.0"));
	QTest::newRow("round(-1.6)")<<func<<oper1<<result<<resoper1<<resresult;
}

void test_math::ddtest_math() 
{
	QFETCH(QString,func);
	QFETCH(variable*,oper1);
    QFETCH(variable*,result);
	QFETCH(variable*,resoper1);
    QFETCH(variable*,resresult);
	mathfunc(func,oper1,result);
	if(oper1->get_vartype()==Real)
		QVERIFY2(abs(oper1->get_value()->f-resoper1->get_value()->f)<0.002,"Changed input variable");
	if(oper1->get_vartype()==Integer)
		QVERIFY2(oper1->get_value()->i==resoper1->get_value()->i,"Changed input variable");
	if(resresult->get_vartype()==Real)
	{
		QVERIFY2(abs(result->get_value()->f-resresult->get_value()->f)<0.002,"Result of function is an expected");
	}
	if(resresult->get_vartype()==Integer)
		QVERIFY2(result->get_value()->i==resresult->get_value()->i,"Result of function is an expected");
}